package cn.rengy.web.framework.wxmp;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import cn.rengy.tool.core.util.ExceptionPrintUtils;
import cn.rengy.tpa.wxmp.component.AuthBody;
import cn.rengy.tpa.wxmp.component.ComponentApp;
import cn.rengy.tpa.wxmp.component.WechatComponentSupport;
import cn.rengy.tpa.wxmp.component.auth.AuthorizationInfo;
import cn.rengy.tpa.wxmp.component.auth.AuthorizerAccessTokenResponse;
import cn.rengy.tpa.wxmp.component.auth.ComponentAccessTokenApi;
import cn.rengy.tpa.wxmp.exception.WeChatException;
import cn.rengy.tpa.wxmp.param.SignatureParam;
import cn.rengy.tpa.wxmp.param.WechatParamName;
import cn.rengy.web.framework.sql.DbService;
import cn.rengy.web.framework.wxmp.component.WxComponentApp;
import cn.rengy.web.framework.wxmp.component.WxComponentAppService;
import cn.rengy.web.framework.wxmp.component.token.ComponentAccessTokenImpl;
import cn.rengy.web.framework.wxmp.component.token.ComponentTokenService;

@Service
public class WechatComponentService extends WechatComponentSupport{
	private static Logger logger = LoggerFactory.getLogger(WechatComponentService.class);
	@Autowired
	private WxComponentAppService wxComponentAppService;
	@Autowired
	private DbService dbService;
	@Autowired
	private ComponentTokenService componentTokenService;
	@Autowired  
	private StringRedisTemplate stringRedisTemplate;
	//@Autowired
	//private RedisComponentTokenRefreshService redisComponentTokenRefreshService;
	public String execute(HttpServletRequest request){
		String result="fail";
		String signature = request.getParameter(WechatParamName.SIGNATURE);
		String timestamp = request.getParameter(WechatParamName.TIMESTAMP);
		String nonce = request.getParameter(WechatParamName.NONCE);
		String echostr = request.getParameter(WechatParamName.ECHOSTR);
		SignatureParam signatureParam =new SignatureParam();
		signatureParam.setEchostr(echostr);
		signatureParam.setNonce(nonce);
		signatureParam.setSignature(signature);
		signatureParam.setTimestamp(timestamp);
		try {
			dispatch( signatureParam,request.getInputStream());
			result="success";
		} catch (Exception e) {
			logger.error(ExceptionPrintUtils.getTrace(e));
		}
		return result;
	}
	
	
	@Override
	protected ComponentApp getComponentApp(String appid) {
		Map<String,Object> map=wxComponentAppService.getWxComponentApp(appid);
		String appsecret=(String)map.get("appsecret");
		String token=(String)map.get("token");
		String aeskey=(String)map.get("aeskey");
		WxComponentApp app=new WxComponentApp();
		app.setAppid(appid);
		app.setAeskey(aeskey);
		app.setAppsecret(appsecret);
		app.setToken(token);
		return app;
	}
	
	/*public void authSuccess(String component_appid,String auth_code,Integer expires_in) throws WeChatException{
		logger.debug("auth_code={},expires_in={}",auth_code,expires_in);
		
	}*/


	@Override
	protected void component_verify_ticket(AuthBody authBody) {
		String ticket=authBody.getComponentVerifyTicket();
		String component_app_id=authBody.getAppid();
		Map<String,Object> tokenMap=this.dbService.queryForMap("select_get_wx_component_token", component_app_id);
		if(tokenMap==null){
			//新增
			this.dbService.update("insert_wx_component_token", component_app_id,ticket);
		}else{
			//更新
			this.dbService.update("update_wx_component_token_ticket", ticket,component_app_id);
		}
	}


	@Override
	protected void authorized(AuthBody authBody){
		logger.info("授权成功");
		logger.debug(authBody.toString());
		/**
		 * 1.新增wx_app或更新授权状态
		 * 2.初始化授权方token
		 */
		try {
			String appid=authBody.getAuthorizerAppid();//授权方appid
			String key=  ComponentTokenService.APP_ACCESS_TOKEN_KEY.concat(appid);
			String component_appid=authBody.getAppid();
			String authorizationCode=authBody.getAuthorizationCode();
			ComponentAccessTokenImpl accessTokenImpl=new ComponentAccessTokenImpl(componentTokenService,component_appid);
			AuthorizerAccessTokenResponse authorizerAccessTokenResponse=ComponentAccessTokenApi.getAuthorizerAccessToken(accessTokenImpl, component_appid, authorizationCode);
			AuthorizationInfo authorizationInfo=authorizerAccessTokenResponse.getAuthorization_info();
			String access_token=authorizationInfo.getAuthorizer_access_token();
			String refresh_token=authorizationInfo.getAuthorizer_refresh_token();
			int access_token_expires_in=authorizationInfo.getExpires_in();
			stringRedisTemplate.opsForValue().set(key, access_token);
			if(stringRedisTemplate.expire(key, access_token_expires_in-60, TimeUnit.SECONDS)){
				//更新数据库信息 令牌和刷新令牌
				Map<String,Object> tokenMap=this.dbService.queryForMap("select_get_wx_app_token", appid);
				if(tokenMap==null){
					this.dbService.update("insert_wx_app_token", appid,component_appid,refresh_token,access_token);
				}else{
					logger.warn("授权成功token已存在");
					this.dbService.update("update_wx_app_token",access_token,refresh_token,appid);
				}
				//更新公众号信息
				Map<String,Object> wxApp=this.dbService.queryForMap("select_get_wx_app", appid);
				if(wxApp==null){
					this.dbService.updateBeanParameter("insert_wx_app_authorized", appid);//已授权
				}else{
					this.dbService.updateBeanParameter("update_wx_app_authorized", appid);//已授权
				}
			}
		} catch (WeChatException e) {
			logger.error(ExceptionPrintUtils.getTrace(e));
		}
	}


	@Override
	protected void unauthorized(AuthBody authBody) {
		logger.info("取消授权");
		String appid=authBody.getAuthorizerAppid();
		/**
		 * 1.更新授权状态
		 * 2.删除token
		 */
		this.dbService.updateBeanParameter("update_wx_app_unauthorized", appid);//取消授权
		String key=  ComponentTokenService.APP_ACCESS_TOKEN_KEY.concat(appid);
		stringRedisTemplate.delete(key);
		this.dbService.updateBeanParameter("delete_wx_app_token", appid);
	}


	@Override
	protected void updateauthorized(AuthBody authBody) {
		logger.info("授权更新");
		logger.debug(authBody.toString());
	}
	

}
